package com.ctvit.cch.core.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctvit.cch.ai.pojo.dto.GenerateCreationDTO;
import com.ctvit.cch.ai.pojo.vo.GenerateCreationVO;
import com.ctvit.cch.ai.service.ILlmService;
import com.ctvit.cch.core.enums.CreationSourceEnum;
import com.ctvit.cch.core.enums.FileTypeEnum;
import com.ctvit.cch.core.enums.GenerateStatusEnum;
import com.ctvit.cch.core.enums.MimeTypeEnum;
import com.ctvit.cch.core.mapper.CreativeIdeaMapper;
import com.ctvit.cch.core.mapper.HotRecordMapper;
import com.ctvit.cch.core.mapper.InspirationCreationMapper;
import com.ctvit.cch.core.mapper.InspirationRecordMapper;
import com.ctvit.cch.core.pojo.domain.CreativeIdea;
import com.ctvit.cch.core.pojo.domain.HotRecord;
import com.ctvit.cch.core.pojo.domain.InspirationCreation;
import com.ctvit.cch.core.pojo.domain.InspirationRecord;
import com.ctvit.cch.core.pojo.dto.creative.InspirationCreationAddDTO;
import com.ctvit.cch.core.pojo.dto.creative.InspirationCreationMoreDTO;
import com.ctvit.cch.core.pojo.dto.creative.InspirationCreationMyDTO;
import com.ctvit.cch.core.pojo.vo.creative.InspirationCreationListVO;
import com.ctvit.cch.core.pojo.vo.creative.InspirationRecordListVO;
import com.ctvit.cch.core.service.IDocumentParseService;
import com.ctvit.cch.core.service.IInspirationCreationService;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Semaphore;
import java.util.stream.Collectors;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartFile;

import com.ruoyi.common.constant.Constants;

/**
 * 灵感创作表 服务实现类
 *
 * @author heyingcheng
 * @date 2025/10/22
 */
@Service
public class InspirationCreationServiceImpl extends ServiceImpl<InspirationCreationMapper, InspirationCreation>
        implements IInspirationCreationService {

    private final Semaphore semaphore = new Semaphore(1);

    private final CreativeIdeaMapper creativeIdeaMapper;

    private final InspirationRecordMapper inspirationRecordMapper;

    private final HotRecordMapper hotRecordMapper;

    private final ILlmService llmService;

    private final IDocumentParseService documentParseService;

    public InspirationCreationServiceImpl(CreativeIdeaMapper creativeIdeaMapper,
            InspirationRecordMapper inspirationRecordMapper,
            HotRecordMapper hotRecordMapper,
            ILlmService llmService,
            IDocumentParseService documentParseService) {
        this.creativeIdeaMapper = creativeIdeaMapper;
        this.inspirationRecordMapper = inspirationRecordMapper;
        this.hotRecordMapper = hotRecordMapper;
        this.llmService = llmService;
        this.documentParseService = documentParseService;
    }

    @Override
    public List<InspirationCreationListVO> getMyList(InspirationCreationMyDTO dto) {
        return baseMapper.getMyList(dto);
    }

    @Override
    public String add(InspirationCreationAddDTO dto) {
        return submitIdea(dto.getRefId());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public List<InspirationRecordListVO> more(InspirationCreationMoreDTO dto) {
        String creationId = dto.getCreationId();
        InspirationCreation one = getById(creationId);
        Assert.notNull(one, "灵感创作不存在");

        try {
            // 获取许可
            semaphore.acquire();
            List<GenerateCreationVO> creations = llmService.generateCreation(new GenerateCreationDTO(one.getTitle(),
                    one.getDescription(), String.format("只允许生成[%s]视角的写作话题", dto.getAngle())));
                    
            int size = creations.size();
            List<InspirationRecord> records = new ArrayList<>(size);
            for (int i = 0; i < size; i++) {
                GenerateCreationVO creationVo = creations.get(i);

                InspirationRecord record = new InspirationRecord();
                record.setCreationId(creationId);
                record.setTitle(creationVo.getTitle());
                record.setKeywords(ObjectUtils.defaultIfNull(creationVo.getKeywords(), Collections.emptyList()));
                record.setContent(creationVo.getDirection());
                record.setAngle(StringUtils.defaultString(creationVo.getAngle()));
                record.setRecordIndex(i);

                records.add(record);
            }

            if (!records.isEmpty()) {
                inspirationRecordMapper.insert(records);
            }

            // 转换为VO并返回
            List<InspirationRecordListVO> result = new ArrayList<>(size);
            for (InspirationRecord record : records) {
                InspirationRecordListVO vo = new InspirationRecordListVO();
                vo.setRecordId(record.getRecordId());
                vo.setCreationId(record.getCreationId());
                vo.setTitle(record.getTitle());
                vo.setContent(record.getContent());
                vo.setAngle(record.getAngle());
                result.add(vo);
            }

            return result;
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new IllegalStateException("任务执行被中断", e);
        } finally {
            // 释放许可
            semaphore.release();
        }
    }

    @Override
    public InspirationCreationListVO get(String id) {
        InspirationCreation one = getById(id);
        Assert.notNull(one, "灵感创作不存在");

        InspirationCreationListVO vo = new InspirationCreationListVO();
        BeanUtils.copyProperties(Objects.requireNonNull(one), vo);

        return vo;
    }

    @Override
    public List<InspirationCreationListVO> listByStatus(String status) {
        // 使用 LambdaQueryWrapper 构造查询条件
        LambdaQueryWrapper<InspirationCreation> queryWrapper = new LambdaQueryWrapper<>();

        queryWrapper.eq(InspirationCreation::getDelFlag, NumberUtils.INTEGER_ZERO.toString());
        queryWrapper.eq(InspirationCreation::getGenerateStatus, status);
        queryWrapper.orderByDesc(InspirationCreation::getUpdateTime);
        queryWrapper.last("LIMIT 10");

        // 执行查询
        List<InspirationCreation> list = list(queryWrapper);

        // 转换为 VO 对象
        return list.stream().map(item -> {
            InspirationCreationListVO vo = new InspirationCreationListVO();
            BeanUtils.copyProperties(Objects.requireNonNull(item), vo);
            return vo;
        }).collect(Collectors.toList());
    }

    @Override
    public boolean updateStatus(String creationId, String currentStatus, String targetStatus) {
        LambdaUpdateWrapper<InspirationCreation> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(InspirationCreation::getCreationId, creationId);
        updateWrapper.eq(InspirationCreation::getDelFlag, NumberUtils.INTEGER_ZERO.toString());
        updateWrapper.eq(InspirationCreation::getGenerateStatus, currentStatus);
        updateWrapper.set(InspirationCreation::getGenerateStatus, targetStatus);
        return update(updateWrapper);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean updateStatus(String creationId, String status, List<InspirationRecord> records) {
        for (InspirationRecord record : records) {
            record.setCreationId(creationId);
            inspirationRecordMapper.insert(record);
        }

        LambdaUpdateWrapper<InspirationCreation> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(InspirationCreation::getCreationId, creationId);
        updateWrapper.eq(InspirationCreation::getDelFlag, NumberUtils.INTEGER_ZERO.toString());
        updateWrapper.set(InspirationCreation::getGenerateStatus, status);
        return update(updateWrapper);
    }

    @Override
    public String submitInsp(String title, String description, String fileType, List<MultipartFile> files)
            throws UncheckedIOException, IOException {
        List<String> lines = new ArrayList<>();

        if (FileTypeEnum.TEXT.name().equals(fileType)) {
            lines.add(description);
        } else if (FileTypeEnum.IMAGE.name().equals(fileType)) {
            
        } else if (FileTypeEnum.FILE.name().equals(fileType)) {
            for (MultipartFile file : files) {
                if (file.isEmpty()) {
                    continue;
                }
                
                // 检查文件大小是否超过 10 MB
                long maxSize = 10 * 1024 * 1024;
                Assert.isTrue(file.getSize() <= maxSize, "文件大小不能超过10MB");

                String originalFilename = file.getOriginalFilename();
                String contentType = file.getContentType();
                String extension = FilenameUtils.getExtension(originalFilename).toUpperCase();

                // 校验扩展名和 MIME 类型
                Assert.isTrue(MimeTypeEnum.isSupportedExtension(extension, FileTypeEnum.FILE), "不支持的文件类型");

                // 进一步校验 MIME 类型（更安全）
                String expectedMimeType = MimeTypeEnum.getMimeTypeByExtension(extension);
                boolean validated = (expectedMimeType != null && contentType != null) &&
                        (contentType.equals(expectedMimeType)
                                || contentType.startsWith("application/vnd.openxmlformats-officedocument.")
                                || contentType.startsWith("application/vnd.ms-")
                                || contentType.startsWith("text/")
                                || contentType.startsWith("image/"));
                Assert.isTrue(validated, "文件类型不符合要求，请上传合法的图片或文档");

                lines.add(documentParseService.extractText(file.getInputStream()));
            }
        }

        InspirationCreation one = new InspirationCreation();
        one.setTitle(title);
        one.setDescription(StringUtils.joinWith(Constants.LINE_SEPARATOR, lines.toArray(new String[0])));
        one.setSource(CreationSourceEnum.INSP.name());
        one.setReferenceLinks(Collections.emptyList());
        one.setGenerateStatus(GenerateStatusEnum.QUEUED.name());

        boolean result = save(one);
        Assert.isTrue(result, "灵感创作保存失败");

        return one.getCreationId();
    }

    @Override
    public String submitIdea(final String refId) {
        CreativeIdea ione = creativeIdeaMapper.selectById(refId);
        Assert.notNull(ione, "灵感创意不存在");

        InspirationCreation cone = new InspirationCreation();
        cone.setRefId(refId);
        cone.setTitle(ione.getTitle());
        cone.setDescription(ione.getDescription());
        cone.setDirection(ione.getDirection());
        cone.setSource(CreationSourceEnum.IDEA.name());
        cone.setReferenceLinks(ione.getReferenceLinks());
        cone.setGenerateStatus(GenerateStatusEnum.QUEUED.name());

        boolean result = save(cone);
        Assert.isTrue(result, "灵感创作保存失败");

        return cone.getCreationId();
    }

    @Override
    public String submitHot(final String refId) {
        HotRecord hone = hotRecordMapper.selectById(refId);
        Assert.notNull(hone, "热榜记录不存在");
        Assert.isTrue(NumberUtils.INTEGER_ZERO.toString().equals(hone.getStatus()), "热榜记录状态错误");

        InspirationCreation cone = new InspirationCreation();
        cone.setRefId(refId);
        cone.setTitle(hone.getTitle());
        cone.setDescription(hone.getRecommendation());
        cone.setSource(CreationSourceEnum.HOT.name());
        cone.setReferenceLinks(
                StringUtils.isNotBlank(hone.getLink()) ? Collections.singletonList(hone.getLink())
                        : Collections.emptyList());
        cone.setGenerateStatus(GenerateStatusEnum.QUEUED.name());

        boolean result = save(cone);
        Assert.isTrue(result, "灵感发散保存失败");

        return cone.getCreationId();
    }

}